package com.zqq.webcloud.AsyncTaskTest;

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.zqq.webcloud.R;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * https://blog.csdn.net/iispring/article/details/50639090
 * * AsyncTask:
 * 1.Params表示用于AsyncTask执行任务的参数的类型
 * 2.Progress表示在后台线程处理的过程中，可以阶段性地发布结果的数据类型
 * 3.Result表示任务全部完成后所返回的数据类型
 * <p>
 * 通过调用AsyncTask的execute()方法传入参数并执行任务:
 */
public class AsyncTaskActivity extends AppCompatActivity {

    TextView textView = null;
    Button btnDownload = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async_task);

        textView = (TextView) findViewById(R.id.textView);
        btnDownload = (Button) findViewById(R.id.btnDownload);
        Log.i("iSpring", "MainActivity -> onCreate, Thread name: " + Thread.currentThread().getName());

    }

    //
    public void onClick(View view) {
        //要下载的文件地址
        String[] urls = {
                "http://blog.csdn.net/iispring/article/details/47115879",
                "http://blog.csdn.net/iispring/article/details/47180325",
                "http://blog.csdn.net/iispring/article/details/47300819",
                "http://blog.csdn.net/iispring/article/details/47320407",
                "http://blog.csdn.net/iispring/article/details/47622705"
        };
//        DownloadTask downloadTask = new DownloadTask();
//
////      1.  只能执行一次execute方法
//        downloadTask.execute(urls);

//      2.如果想并行地执行多个任务怎么办呢？我们可以考虑实例化多个AsyncTask实例
//        DownloadTask downloadTask2 = new DownloadTask();
//        downloadTask2.execute(urls);
//        这些实例的execute方法并不是并行执行的，是串行执行的，即在第一个实例的doInBackground完成任务后，
// 第二个实例的doInBackgroud方法才会开始执行，然后再执行第三个实例的doInBackground方法

        //3.Android 3.0开始AsyncTask增加了executeOnExecutor方法，用该方法可以让AsyncTask并行处理任务
        //方法签名如下：
        //public final AsyncTask<Params, Progress, Result> executeOnExecutor (Executor exec, Params... params)
        //第一个参数表示exec是一个Executor对象：通常情况下我们此处传入AsyncTask.THREAD_POOL_EXECUTOR（线程池对象）即可
        //第二个参数params表示的是要执行的任务的参数。
        DownloadTask task1 = new DownloadTask();
        task1.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, urls);

        DownloadTask task2 = new DownloadTask();
        task2.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, urls);
    }

    /**
     * 在此例中，Params泛型是String类型，Progress泛型是Object类型，Result泛型是Long类型
     */
    private class DownloadTask extends AsyncTask<String, Object, Long> {

        //        执行了execute()方法后就会执行onPreExecute(主线程)方法，通常可以在该方法中显示一个进度条
        @Override
        protected void onPreExecute() {
            Log.i("iSpring", "DownloadTask -> onPreExecute, Thread name: " + Thread.currentThread().getName());
            super.onPreExecute();
            btnDownload.setEnabled(false);
            textView.setText("开始下载...");
        }

        //        会在onPreExecute()方法执行完成后立即执行，（UI线程即主线程）
//        调用AsyncTask的publishProgress(Progress…)将阶段性的处理结果发布出去，并在UI线程中回调onProgressUpdate方法
        @Override
        protected Long doInBackground(String... params) {
            Log.i("iSpring", "DownloadTask -> doInBackground, Thread name: " + Thread.currentThread().getName());
            //totalByte表示所有下载的文件的总字节数
            long totalByte = 0;

//            params是一个string数组(即execute中的参数)
            for (String url : params) {
                //遍历Url数组，依次下载对应的文件
                Object[] result = downloadSingleFile(url);
                int byteCount = (int) result[0];

                totalByte += byteCount;

                //在下载完一个文件之后，我们就把阶段性的处理结果发布出去
                publishProgress(result);

                //如果AsyncTask被调用了cancel()方法，那么任务取消，跳出for循环
                if (isCancelled()) {
                    break;
                }
            }
            //将总共下载的字节数作为结果返回
            return totalByte;
        }

        //下载文件后返回一个Object数组：下载文件的字节数以及下载的博客的名字
        private Object[] downloadSingleFile(String str) {
            Object[] result = new Object[2];
            int byteCount = 0;      //记录文件字节数
            String blogName = "";

            HttpURLConnection conn = null;

            try {
                URL url = new URL(str);
                conn = (HttpURLConnection) url.openConnection();

                InputStream is = conn.getInputStream();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buf = new byte[1024];
                int len = -1;
                while ((len = is.read(buf)) != -1) {
                    baos.write(buf, 0, len);
                    byteCount += len;
                }

                String response = new String(baos.toByteArray(), "UTF-8");
                Log.e("iSpring", response);

                int startIndex = response.indexOf("<title>");
                if (startIndex > 0) {
                    startIndex += 7;
                    int endIndex = response.indexOf("</title>");
                    if (endIndex > startIndex) {
                        //解析出博客中的标题
                        blogName = response.substring(startIndex, endIndex);
                    }
                }

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (conn != null) {
                    conn.disconnect();
                }
            }
            result[0] = byteCount;
            result[1] = blogName;
            return result;
        }


        @Override
        protected void onProgressUpdate(Object... values) {
            Log.i("iSpring", "DownloadTask -> onProgressUpdate, Thread name: " + Thread.currentThread().getName());
            super.onProgressUpdate(values);
            int byteCount = (int) values[0];
            String blogName = (String) values[1];
            String text = textView.getText().toString();
            text += "\n博客《" + blogName + "》下载完成，共 " + byteCount + " 字节";
            textView.setText(text);
        }


        //        当doInBackgroud方法执行完毕后，拿到返回值，这样就可以在主线程中根据任务的执行结果更新UI。
        @Override
        protected void onPostExecute(Long aLong) {
            Log.i("iSpring", "DownloadTask -> onPostExecute, Thread name: " + Thread.currentThread().getName());
            super.onPostExecute(aLong);
            String text = textView.getText().toString();
            text += "\n全部下载完成，总共下载了 " + aLong + " 个字节";
            textView.setText(text);
            btnDownload.setEnabled(true);
        }

        @Override
        protected void onCancelled() {
            Log.i("iSpring", "DownloadTask -> onCancelled, Thread name: " + Thread.currentThread().getName());
            super.onCancelled();
            textView.setText("取消下载");
            btnDownload.setEnabled(true);
        }
    }
}
